/*
 * SPDX-FileCopyrightText: 2022-2024 Andrew Gunnerson
 * SPDX-License-Identifier: GPL-3.0-only
 */

@file:OptIn(ExperimentalUnsignedTypes::class)

package com.sanji.audio_test.format

import android.media.MediaFormat
import android.media.MediaMuxer
import android.os.Build
import androidx.annotation.RequiresApi
import java.io.FileDescriptor

/**
 * Opus 音频格式实现类
 * 仅支持 Android 10 及以上版本
 */
class OpusFormat : Format() {
    // 初始化块，检查 Android 版本是否符合要求
    init {
        require(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            "仅支持 Android 10 及更新版本"
        }
    }

    // 格式名称
    override val name: String = "OGG/Opus"
    
    // 容器 MIME 类型，参考 RFC 7845 第9节
    // https://datatracker.ietf.org/doc/html/rfc7845#section-9
    override val mimeTypeContainer: String = "audio/ogg"
    
    // 音频 MIME 类型
    override val mimeTypeAudio: String = MediaFormat.MIMETYPE_AUDIO_OPUS
    
    // 是否支持直通模式（不重新编码）
    override val passthrough: Boolean = false
    
    // 参数信息，定义比特率范围和推荐值
    override val paramInfo: FormatParamInfo = RangedParamInfo(
        RangedParamType.Bitrate,
        6_000u..510_000u,  // 比特率范围：6 kbps 到 510 kbps
        48_000u,           // 默认比特率：48 kbps
        // 推荐比特率设置，参考 hydrogenaud.io
        // https://wiki.hydrogenaud.io/index.php?title=Opus
        uintArrayOf(
            // "中等带宽，优于电话质量"
            12_000u,
            // "接近透明的语音质量"
            24_000u,
            // "基本透明的单声道或立体声语音，合理的音乐质量"
            48_000u,
        ),
    )
    
    // 采样率信息，基于编解码器默认为 16000 Hz
    override val sampleRateInfo: SampleRateInfo =
        SampleRateInfo.fromCodec(baseMediaFormat, 16_000u)

    /**
     * 更新媒体格式参数
     * @param mediaFormat 媒体格式对象
     * @param param 指定的比特率参数
     */
    override fun updateMediaFormat(mediaFormat: MediaFormat, param: UInt) {
        mediaFormat.apply {
            val channelCount = getInteger(MediaFormat.KEY_CHANNEL_COUNT)
            // 设置比特率，考虑声道数的影响
            setInteger(MediaFormat.KEY_BIT_RATE, param.toInt() * channelCount)
        }
    }

    /**
     * 获取容器对象
     * @param fd 文件描述符
     * @return OGG 容器对象
     */
    @RequiresApi(Build.VERSION_CODES.Q)
    override fun getContainer(fd: FileDescriptor): Container =
        MediaMuxerContainer(fd, MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG)
}